home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 4 / Mac Giga-ROM 4.0 - 1993.toast / FILES / DEV / A-B / Acius09:92.cpt / Acius09_92 / CustomOpenDLGƒ / Ext4D_Files_Package.p < prev    next >
Text File  |  1992-08-26  |  31KB  |  1,083 lines

  1. {===================================================================================================}
  2. {
  3.     Custom Open File Dialog Box external commands for 4th DIMENSION 2.x.x
  4.     by Dominique Hermsdorff
  5.     ©1992 ACI,ACIUS Inc.
  6.     
  7.     To work with this source code, you have to be familiar with :
  8.         - the File Manager,
  9.         - the List Manager,
  10.         - the Standard File Package.
  11.     See the relevant Inside Macintosh volumes in this purpose and also the Apple Technical Note
  12.     #047- Customizing Standard File.
  13.  
  14.     About the Custom Open File Dialog Box external commands...
  15.     
  16.     These commands and the source code are provided to you for your information.
  17.     They are intended to help you in the implementation of your own external commands.
  18.     They are not intended to be used as is, in final applications.
  19.     
  20.     If you would like to use these commands inside your applications, please use,
  21.     or contact a developer able to use, the source code provided as a template
  22.     to build your own commands.
  23.     
  24.     Note: ACI and ACIUS Technical Support do not provide support for these external commands.
  25.     
  26. }
  27. {===================================================================================================}
  28.  
  29. UNIT EXT4D_FILES_PACKAGE;
  30.  
  31. {$IFC Undefined THINK_PASCAL }
  32.     {$D- }
  33.     {$R- }
  34. {$ENDC }
  35.  
  36. INTERFACE
  37.  
  38. {$IFC Undefined THINK_PASCAL }
  39.     Uses    MemTypes,
  40.                 QuickDraw,
  41.                 OSIntf,
  42.                 OSUtils,
  43.                 ToolIntf,
  44.                 Lists,
  45.                 StandardFile,
  46.                 SysEqu,
  47.                 Traps,
  48.                 Ext4DIntf;
  49. {$ENDC}
  50.  
  51. {$IFC Undefined THINK_PASCAL }
  52.     {$SETC DebugOn = TRUE }
  53.     {$IFC DebugOn }
  54.         {$D+ }
  55.         {$R+ }
  56.     {$ELSEC }
  57.         {$D- }
  58.         {$R- }
  59.     {$ENDC }
  60. {$ENDC }
  61.  
  62. {$IFC UNDEFINED THINK_PASCAL }
  63.     {$R- }
  64. {$ENDC }
  65.  
  66.  
  67. PROCEDURE CALL_FILES_PACKAGE(ProcNum:LongInt;Params:ParamsTabPtr;Var Data:Handle;Var FuncPtr:Ptr);
  68.  
  69. IMPLEMENTATION
  70.  
  71. PROCEDURE FILES_PACKAGE(ProcNum:LongInt;Params:ParamsTabPtr;Var Data:Handle;Var FuncPtr:Ptr);FORWARD;
  72.                                                          
  73. PROCEDURE CALL_FILES_PACKAGE(ProcNum:LongInt;Params:ParamsTabPtr;Var Data:Handle;Var FuncPtr:Ptr);
  74. BEGIN
  75.     FILES_PACKAGE(ProcNum,Params,Data,FuncPtr);
  76. END; { CALL_FILES_PACKAGE }
  77.  
  78.  
  79. CONST        kOpenMFile                    =    1;
  80.                 kOpenSFile                    =    2;
  81.                 kSetFPos                        =    3;
  82.                 kGetEOF                            =    4;
  83.                 kGetFileInfo                = 5;
  84.                 
  85.                 kMultipleOpenDlgID    =    1;
  86.                 kSingleOpenDlgID        =    2;
  87.                     kMessageItem            =    11;
  88.                     kListItem                    =    12;
  89.                     kRemoveItem                =    13;
  90.                     kDoneItem                    = 14;
  91.                 
  92.                 HWCfgFlags                     = $B22;
  93.                 
  94.                 Enter                                =    $03;
  95.                 BackSpace                     =    $08;
  96.                 Return                            =    $0D;
  97.                 AsciiUp                            =    $1E;
  98.                 AsciiDown                        =    $1F;
  99.                 
  100.                 CommandKeyCode            =    55;
  101.                 ShiftKeyCode                =    56;
  102.                 CapsLockKeyCode            =    57;
  103.                 OptionKeyCode                = 58;
  104.                 ControlKeyCode            =    59;
  105.                 
  106.                 OKButton                        =    1;
  107.                 DevToolDlgID                =    0;
  108.  
  109.                 
  110. TYPE        IntegerHandle    =    ^IntegerPtr;
  111.  
  112.                 SFReplyPtr        =    ^SFReply;
  113.                 
  114.                 DlgDataHandle    =    ^DlgDataPtr;
  115.                 DlgDataPtr        =    ^DlgDataRecord;
  116.                 DlgDataRecord    =    RECORD
  117.                                                     SFDlgID                : INTEGER;                {  2 bytes }
  118.                                                     UserReplyPtr    : SFReplyPtr;            {  4 bytes }
  119.                                                     FileList            : ListHandle;            {  4 bytes }
  120.                                                     Array4D                : VarRecPtr;            {  4 bytes }
  121.                                                     FilterProc        : STRING[63];            { 64 bytes }
  122.                                                 END;                                                            { 78 bytes in total }
  123.  
  124. FUNCTION KeyIsDown(WhichKey:INTEGER):BOOLEAN;
  125. VAR    Keyboard:KeyMap;
  126. BEGIN
  127.     GetKeys(KeyBoard);
  128.     KeyIsDown:=KeyBoard[WhichKey];
  129. END; { KeyIsDown }
  130.  
  131. PROCEDURE    MySetCursor(WhichCursor:INTEGER);
  132. BEGIN
  133.     SetCursor(GetCursor(GetResNum('4BNX','CURS',WhichCursor))^^);
  134. END; { MySetCursor }
  135.  
  136. PROCEDURE    GetPathName(vRefNum:INTEGER;ParentDirectory:LongInt;FileName:StringPtr);
  137. VAR        ErrCode:INTEGER;
  138.             DirSep:String[1];
  139.             MFSBlock:ParamBlockRec;
  140.             HFSBlock:HParamBlockRec;
  141.             CatBlock:CInfoPBRec;
  142.             ParentName:Str255;
  143. BEGIN
  144.     IF IntegerPtr($3F6)^> 0 THEN
  145.     BEGIN
  146.         ParentName:='';
  147.         WITH HFSBlock DO
  148.         BEGIN
  149.             ioCompletion:=NIL;
  150.             ioNamePtr:=@ParentName;
  151.             ioVolIndex:=0;
  152.             ioVRefNum:=vRefNum;
  153.         END; { With HFSBlock Do }
  154.         ErrCode:=PBHGetVInfo(@HFSBlock,FALSE);
  155.         IF ErrCode=NoErr THEN
  156.         BEGIN
  157.             IF BTst(LongInt(IntegerPtr(HWCfgFlags)^),9) THEN DirSep:='/' ELSE DirSep:=':';
  158.             IF HFSBlock.IOVSigWord=$D2D7 THEN FileName^:=CONCAT(ParentName,DirSep,FileName^)
  159.             ELSE
  160.             BEGIN
  161.                 CatBlock.ioDrParID:=ParentDirectory;
  162.                 REPEAT
  163.                     ParentName:='';
  164.                     WITH CatBlock DO
  165.                     BEGIN
  166.                         ioCompletion:=NIL;
  167.                         ioNamePtr:=@ParentName;
  168.                         ioVRefNum:=vRefNum;
  169.                         ioFDirIndex:=-1;
  170.                         ioDirID:=0;
  171.                         ioDrDirID:=ioDrParID;
  172.                     END;
  173.                     ErrCode:=PBGetCatInfo(@CatBlock,FALSE);
  174.                     IF ErrCode=NoErr THEN
  175.                     BEGIN
  176.                         IF Length(FileName^)+Length(ParentName)<255 THEN FileName^:=CONCAT(ParentName,DirSep,FileName^)    
  177.                         ELSE
  178.                         BEGIN
  179.                             FileName^:='';
  180.                             ErrCode:=1;
  181.                         END;
  182.                     END
  183.                     ELSE FileName^:='';
  184.                 UNTIL (CatBlock.ioDrDirID=fsRtDirID) | (ErrCode<>NoErr);
  185.             END;
  186.         END
  187.         ELSE FileName^:='';
  188.     END
  189.     ELSE
  190.     BEGIN
  191.         ParentName:='';
  192.         WITH MFSBlock DO
  193.         BEGIN
  194.             ioCompletion:=NIL;
  195.             ioNamePtr:=@ParentName;
  196.             ioVolIndex:=0;
  197.             ioVRefNum:=vRefNum;
  198.         END;
  199.         ErrCode:=PBGetVInfo(@MFSBlock,FALSE);
  200.         IF ErrCode=NoErr THEN FileName^:=Concat(ParentName,DirSep,FileName^) ELSE FileName^:='';
  201.     END;
  202. END; { GetPathName }
  203.  
  204. PROCEDURE DisposeExpression(Expression:VarRecPtr);
  205. BEGIN
  206.     WITH Expression^ DO
  207.     BEGIN
  208.         CASE VarKind OF
  209.             Alpha    : IF CC<>NIL THEN DisposHandle(Handle(CC));
  210.             Pict    : IF PP<>NIL THEN DisposHandle(Handle(PP));
  211.         END;
  212.     END;
  213. END; { DisposeExpression }
  214.  
  215. FUNCTION Call4DLongIntFunction(FunctionText:Handle):LongInt;
  216. VAR    CurPort:GrafPtr;
  217.         MyWind:WindowPtr;
  218.         Blk4D:ParmBlock;
  219.         FunctionResult:VarRec;
  220. BEGIN
  221.     Call4DLongIntFunction:=0;
  222.     Blk4D.HH:=FunctionText;                                                        { Pass the text to be executed }
  223.     FunctionResult.VarKind:=Nothing;                                    { Set the function result to undefined }
  224.     Blk4D.Result1:=ORD4(@FunctionResult);                            { Pass the function result record }
  225.     MyWind:=FrontWindow;                                                            { See note below }
  226.     GetPort(CurPort);                                                                { See note below }
  227.     Call4D(EX_Execute_function,Blk4D);                                { Call 4D }
  228.     SetPort(CurPort);                                                                    { See note below }
  229.     IF MyWind<>NIL THEN SelectWindow(MyWind);                    { See note below }
  230.     DisposHandle(FunctionText);                                                { We do not need the text anymore }
  231.     WITH FunctionResult DO
  232.         IF (VarKind=Long4D) THEN                                                { Did the 4D function return a LongInt value? }
  233.             Call4DLongIntFunction:=LValue;                                { If so, get it }
  234.     DisposeExpression(@FunctionResult);                                { Necessary if the function mistakely returns
  235.                                                                                                             a text or a picture }
  236.     { IMPORTANT NOTE
  237.         --------------
  238.         We call back 4th DIMENSION from the file filtering function, which is itself called
  239.         by the Standard File Package. Although it is not a good idea, we may call the TRACE window
  240.         or display a window in the 4th DIMENSION function
  241.         We do not have any way to forbide such a command from our package.
  242.         In such a case, 4th DIMENSION does not know anything about our dialog. In other words,
  243.         4th DIMENSION will not save and restore the current GrafPort. This is why we do it by ourselves.
  244.         We call SelectWindow in order to solve the problem of the TRACE window which may appear
  245.         above our SFP dialog. }
  246.     
  247. END; { Call4DLongIntFunction }
  248.  
  249. PROCEDURE ClearArray(VAR anArray:VarRec);
  250. VAR    z:LongInt;
  251.         h:Handle;
  252.         s:StringPtr;
  253. BEGIN
  254.     WITH anArray DO
  255.     BEGIN
  256.         IF NbElem>0 THEN
  257.         BEGIN
  258.             IF VarKind=TabAlpha THEN
  259.             BEGIN
  260.                 IF TabAlphaH<>NIL THEN
  261.                 BEGIN
  262.                     FOR z:=0 TO NbElem DO
  263.                     BEGIN
  264.                         h:=Handle(TabAlphaH^^[z].CC);
  265.                         IF h<>NIL THEN DisposHandle(h);
  266.                     END;
  267.                 END;
  268.             END
  269.             ELSE
  270.             BEGIN
  271.                 IF VarKind=TabPict THEN
  272.                 BEGIN
  273.                     FOR z:=0 TO NbElem DO
  274.                     BEGIN
  275.                         h:=Handle(TabPictH^^[z]);
  276.                         IF h<>NIL THEN DisposHandle(h);
  277.                     END;
  278.                 END;
  279.             END;
  280.             CASE VarKind OF
  281.                 TabInt            : z:=SizeOf(Integer);
  282.                 TabLong            : z:=SizeOf(LongInt);
  283.                 TabNum            : z:=SizeOf(Extended);
  284.                 TabAlpha        :    z:=SizeOf(TE4D);
  285.                 TabPict            :    z:=SizeOf(PicHandle);
  286.                 TabDate            : z:=SizeOf(Date4D);
  287.                 TabBool            : z:=2;
  288.                 TabStrFix        : BEGIN
  289.                                                 z:=ORD4(TabFixH^^.LenFix);
  290.                                                 IF ODD(z) THEN z:=z+1;
  291.                                                 z:=z+2;
  292.                                             END;
  293.             END;
  294.             IF TabIntH<>NIL THEN SetHandleSize(Handle(TabIntH),z);                    
  295.             NbElem:=0;
  296.             CurSel:=0;
  297.             CASE VarKind OF
  298.                 TabBool,
  299.                 TabInt            : TabIntH^^[0]:=0;
  300.                 TabLong            : TabLongH^^[0]:=0;
  301.                 TabNum            : TabNumH^^[0]:=0;
  302.                 TabAlpha        :    WITH TabAlphaH^^[0] DO
  303.                                             BEGIN
  304.                                                 Len:=0;
  305.                                                 CC:=NIL;
  306.                                             END;
  307.                 TabPict            :    TabPictH^^[0]:=NIL;
  308.                 TabDate            : WITH TabDateH^^[0] DO
  309.                                             BEGIN
  310.                                                 Day:=0;
  311.                                                 Month:=0;
  312.                                                 Year:=0;
  313.                                             END;
  314.                 TabStrFix        : BEGIN
  315.                                                 s:=StringPtr(ORD4(TabFixH^)+2);
  316.                                                 s^:='';
  317.                                             END;
  318.             END;
  319.         END;
  320.     END;
  321. END; { ClearArray }
  322.  
  323. FUNCTION ResizeArray(VAR anArray:VarRec;Nb:LongInt):OSErr;
  324. VAR n:INTEGER;
  325.         z:LongInt;
  326.         h:Handle;
  327. BEGIN
  328.     ResizeArray:=NoErr;
  329.     ClearArray(anArray);
  330.     WITH anArray DO
  331.     BEGIN
  332.         Nb:=Nb+1;
  333.         CASE VarKind OF
  334.             TabInt            : z:=Nb*SizeOf(INTEGER);
  335.             TabLong            : z:=Nb*SizeOf(LongInt);
  336.             TabNum            : z:=Nb*SizeOf(Extended);
  337.             TabAlpha        :    z:=Nb*SizeOf(TE4D);
  338.             TabPict            :    z:=Nb*SizeOf(PicHandle);
  339.             TabDate            : z:=Nb*SizeOf(Date4D);
  340.             TabBool            : z:=2+(Nb DIV 8);
  341.             TabStrFix        : BEGIN
  342.                                             n:=TabFixH^^.LenFix;
  343.                                             z:=ORD4(n);
  344.                                             IF ODD(z) THEN z:=z+1;
  345.                                             z:=2+(Nb*z);
  346.                                         END;
  347.         END;
  348.         Nb:=Nb-1;
  349.         h:=NewHandleClear(z);
  350.         IF h<>NIL THEN
  351.         BEGIN
  352.             IF TabIntH<>NIL THEN DisposHandle(Handle(TabIntH));
  353.             TabIntH:=TabOfIntHandle(h);
  354.             NbElem:=Nb;
  355.             CurSel:=0;
  356.             IF VarKind=TabStrFix THEN IntegerHandle(TabFixH)^^:=n;
  357.         END
  358.         ELSE ResizeArray:=MemFullErr;
  359.     END;
  360. END; { ResizeArray }
  361.  
  362. FUNCTION StringArrayFixLen(anArray:VarRecPtr):LongInt;
  363. VAR    z:LongInt;
  364. BEGIN
  365.     WITH anArray^ DO
  366.     BEGIN
  367.         IF VarKind=TabStrFix THEN
  368.         BEGIN
  369.             z:=ORD4(TabFixH^^.LenFix);
  370.             IF ODD(z) THEN z:=z+1;
  371.         END
  372.         ELSE z:=0;
  373.     END;
  374.     StringArrayFixLen:=z;
  375. END; { StringArrayFixLen }
  376.  
  377. FUNCTION AddStringElement(StrValue:StringPtr;Element:LongInt;anArray:VarRecPtr):BOOLEAN;
  378. VAR    z,n:LongInt;
  379.         h:Handle;
  380. BEGIN
  381.     AddStringElement:=TRUE;
  382.     WITH anArray^ DO
  383.     BEGIN
  384.         z:=ORD4(Length(StrValue^));
  385.         IF VarKind=TabAlpha THEN
  386.         BEGIN
  387.             h:=NewHandle(z);
  388.             IF h<>NIL THEN
  389.             BEGIN
  390.                 IF z>0 THEN BlockMove(Ptr(ORD4(StrValue)+1),Ptr(h^),z);
  391.                 WITH TabAlphaH^^[Element] DO
  392.                 BEGIN
  393.                     CC:=CharsHandle(h);
  394.                     Len:=ORD(z);
  395.                 END;
  396.             END
  397.             ELSE AddStringElement:=FALSE;
  398.         END
  399.         ELSE
  400.         BEGIN
  401.             IF z>0 THEN
  402.             BEGIN
  403.                 n:=StringArrayFixLen(anArray);
  404.                 z:=z+1;
  405.                 IF z>n THEN z:=n;
  406.                 BlockMove(Ptr(StrValue),Ptr(ORD4(TabFixH^)+2+(Element*n)),z);
  407.             END;
  408.         END;
  409.     END;
  410. END; { AddStringElement }
  411.  
  412. PROCEDURE SetDocumentVar(FileName:StringPtr);
  413. VAR Error:INTEGER;
  414.     Blk4D:ParmBlock;
  415.     DocVar:VarRec;
  416. BEGIN
  417.   WITH Blk4D DO
  418.     BEGIN
  419.         Name:='Document';
  420.         HH:=Handle(@DocVar);
  421.     END;
  422.     Call4D(EX_GET_VARIABLE,Blk4D);
  423.     IF Blk4D.Error=NoErr THEN
  424.     BEGIN
  425.       Error:=NoErr;
  426.         WITH DocVar DO
  427.         BEGIN
  428.             CASE VarKind OF
  429.               Nothing,
  430.                 Alpha        :    BEGIN
  431.                                     Len:=Length(FileName^);
  432.                                         IF (VarKind=Nothing) THEN
  433.                                         BEGIN
  434.                                           CC:=CharsHandle(NewHandle(ORD4(Len)));
  435.                                             IF CC=NIL THEN Error:=MemFullErr;
  436.                                             VarKind:=Alpha;
  437.                                         END
  438.                                         ELSE
  439.                                         BEGIN
  440.                                             Blk4D.ClearOldVariable:=FALSE;
  441.                                             IF CC=NIL THEN
  442.                                             BEGIN
  443.                                                 CC:=CharsHandle(NewHandle(ORD4(Len)));
  444.                                               IF CC=NIL THEN Error:=MemFullErr;
  445.                                             END
  446.                                             ELSE
  447.                                             BEGIN
  448.                                                 SetHandleSize(Handle(CC),ORD4(Len));
  449.                                                 Error:=MemError;
  450.                                             END;
  451.                                         END;
  452.                                         IF (Error=NoErr) & (Len>0) THEN BlockMove(Ptr(ORD4(FileName)+1),Ptr(CC^),ORD4(Len));
  453.                                END;
  454.               StrFix    : BEGIN
  455.                                       SLen:=Length(FileName^);
  456.                                         SValue:=FileName^;
  457.                             END;
  458.               OTHERWISE Error:=-1;
  459.             END;
  460.         END;
  461.         IF Error=NoErr THEN Call4D(EX_PUT_VARIABLE,Blk4D);
  462.     END;
  463. END; { SetDocumentVar }
  464.  
  465. PROCEDURE AddStringToText(Str:StringPtr;Data:Handle);
  466. VAR    StrLen,DataLen:LongInt;
  467. BEGIN
  468.     StrLen:=ORD4(Length(Str^));
  469.     IF StrLen>0 THEN
  470.     BEGIN
  471.         DataLen:=GetHandleSize(Data);
  472.         SetHandleSize(Data,DataLen+StrLen);
  473.         IF MemError=NoErr THEN BlockMove(Ptr(ORD4(Str)+1),Ptr(ORD4(Data^)+DataLen),StrLen);
  474.     END;
  475. END; { AddStringToText }
  476.  
  477. {$I    Ext4D_DevTools_Dlg.p }
  478.  
  479. PROCEDURE    MySetUItem(MyDlg:DialogPtr;MyItem:INTEGER;ItemProc:ProcPtr);
  480. VAR    Kind:INTEGER;
  481.         Content:Handle;
  482.         ItemRect:Rect;
  483. BEGIN
  484.     GetDItem(MyDlg,MyItem,Kind,Content,ItemRect);
  485.     SetDItem(MyDlg,MyItem,UserItem,Handle(ItemProc),ItemRect);
  486. END; { MySetUItem }
  487.  
  488. PROCEDURE    HiliteCtlItem(MyDlg:DialogPtr;MyItem:INTEGER;Value:INTEGER);
  489. VAR    Kind:INTEGER;
  490.         Content:Handle;
  491.         ItemRect:Rect;
  492. BEGIN
  493.     GetDItem(MyDlg,MyItem,Kind,Content,ItemRect);
  494.     HiliteControl(ControlHandle(Content),Value);
  495. END; { HiliteCtlItem }
  496.  
  497. PROCEDURE HiliteDlgButton(MyDlg:DialogPtr;MyItem:INTEGER);
  498. VAR    finalTicks:LongInt;
  499. BEGIN
  500.     HiliteCtlItem(MyDlg,MyItem,1);
  501.     Delay(8,finalTicks);
  502.     HiliteCtlItem(MyDlg,MyItem,0);
  503. END; { HiliteDlgButton }
  504.  
  505. FUNCTION LNbOfRows(List:ListHandle):INTEGER;
  506. BEGIN
  507.     LNbOfRows:=List^^.DataBounds.Bottom;
  508. END;
  509.  
  510. PROCEDURE LGetString(List:ListHandle;Row,Column:INTEGER;Value:StringPtr);
  511. VAR    Len:INTEGER;
  512.         Data:Handle;
  513.         TargetCell:Point;
  514. BEGIN
  515.     Value^:='';
  516.     Data:=NewHandle(255);
  517.     IF Data<>NIl THEN
  518.     BEGIN
  519.         HLock(Data);
  520.         Len:=255;
  521.         TargetCell.H:=Column;
  522.         TargetCell.V:=Row;
  523.         LGetCell(Ptr(Data^),Len,TargetCell,List);
  524.         IF Len>0 THEN BlockMove(Ptr(Data^),Ptr(ORD4(Value)+1),ORD4(Len));
  525.         Value^[0]:=Chr(Len);
  526.         HUnLock(Data);
  527.         DisposHandle(Data);
  528.     END;
  529. END; { LGetString }
  530.  
  531. FUNCTION LGetInteger(List:ListHandle;Row,Column:INTEGER):INTEGER;
  532. VAR    Len,Value:INTEGER;
  533.         TargetCell:Point;
  534. BEGIN
  535.     Value:=0;
  536.     Len:=2;
  537.     TargetCell.H:=Column;
  538.     TargetCell.V:=Row;
  539.     LGetCell(Ptr(@Value),Len,TargetCell,List);
  540.     LGetInteger:=Value;
  541. END; { LGetInteger }
  542.     
  543. FUNCTION LGetLongInt(List:ListHandle;Row,Column:INTEGER):LongInt;
  544. VAR    Len:INTEGER;
  545.         Value:LongInt;
  546.         TargetCell:Point;
  547. BEGIN
  548.     Value:=0;
  549.     Len:=4;
  550.     TargetCell.H:=Column;
  551.     TargetCell.V:=Row;
  552.     LGetCell(Ptr(@Value),Len,TargetCell,List);
  553.     LGetLongInt:=Value;
  554. END; { LGetLongInt }
  555.  
  556. PROCEDURE LPutString(List:ListHandle;Row,Column:INTEGER;Value:StringPtr);
  557. VAR    Len:INTEGER;
  558.         Data:Handle;
  559.         TargetCell:Point;
  560. BEGIN
  561.     Len:=Length(Value^);
  562.     IF Len>0 THEN
  563.     BEGIN
  564.         Data:=NewHandle(Len);
  565.         IF Data<>NIl THEN
  566.         BEGIN
  567.             HLock(Data);
  568.             BlockMove(Ptr(ORD4(Value)+1),Ptr(Data^),ORD4(Len));
  569.             TargetCell.H:=Column;
  570.             TargetCell.V:=Row;
  571.             LSetCell(Ptr(Data^),Len,TargetCell,List);
  572.             HUnLock(Data);
  573.             DisposHandle(Data);
  574.         END;
  575.     END;
  576. END; { LPutString }
  577.  
  578. PROCEDURE LPutInteger(List:ListHandle;Row,Column:INTEGER;Value:INTEGER);
  579. VAR    TargetCell:Point;
  580. BEGIN
  581.     TargetCell.H:=Column;
  582.     TargetCell.V:=Row;
  583.     LSetCell(Ptr(@Value),2,TargetCell,List);
  584. END; { LPutInteger }
  585.  
  586. PROCEDURE LPutLongInt(List:ListHandle;Row,Column:INTEGER;Value:LongInt);
  587. VAR    TargetCell:Point;
  588. BEGIN
  589.     TargetCell.H:=Column;
  590.     TargetCell.V:=Row;
  591.     LSetCell(Ptr(@Value),4,TargetCell,List);
  592. END; { LPutInteger }
  593.  
  594. FUNCTION LSearchFile(FileName:StringPtr;
  595.                                          vRefNum:INTEGER;
  596.                                          DirID:LongInt;
  597.                                          List:ListHandle;VAR ExactMatch:INTEGER):INTEGER;
  598. VAR    Count,Comparison,Where,NbOfRows:INTEGER;
  599.         Str:Str255;
  600. BEGIN
  601.     ExactMatch:=-1;
  602.     Where:=32000;
  603.     NbOfRows:=LNbOfRows(List);
  604.     IF NbOfRows>0 THEN
  605.     BEGIN
  606.         FOR Count:=0 TO NbOfRows DO
  607.         BEGIN
  608.             LGetString(List,Count,0,@Str);
  609.             Comparison:=RelString(FileName^,Str,FALSE,TRUE);
  610.             IF Comparison<=0 THEN
  611.             BEGIN
  612.                 IF Where<>32000 THEN Where:=Count;
  613.                 IF Comparison=0 THEN
  614.                     IF LGetInteger(List,Count,1)=vRefNum THEN
  615.                         IF LGetLongInt(List,Count,2)=DirID THEN ExactMatch:=Count;
  616.             END;
  617.         END;
  618.     END;
  619.     LSearchFile:=Where;
  620. END; { LSearchFile }
  621.  
  622. PROCEDURE LDeleteSelection(List:ListHandle);
  623. VAR    NbOfRows:INTEGER;
  624.         aCell:Point;
  625. BEGIN
  626.     aCell.H:=0;
  627.     aCell.V:=0;
  628.     IF LGetSelect(TRUE,aCell,List) THEN
  629.     BEGIN
  630.         LDelRow(1,aCell.V,List);
  631.         NbOfRows:=LNbOfRows(List);
  632.         IF NbOfRows>0 THEN
  633.         BEGIN
  634.             IF aCell.V>=NbOfRows THEN aCell.V:=NbOfRows-1;
  635.             LSetSelect(TRUE,aCell,List);
  636.         END;
  637.     END;
  638. END; { LDeleteSelection }
  639.  
  640. FUNCTION LGetSelection(List:ListHandle):INTEGER;
  641. VAR    aCell:Point;
  642. BEGIN
  643.     aCell.H:=0;
  644.     aCell.V:=0;
  645.     IF LGetSelect(TRUE,aCell,List) THEN LGetSelection:=aCell.V
  646.     ELSE LGetSelection:=-1;
  647. END; { LGetSelection }
  648.  
  649. PROCEDURE LSetSelection(List:ListHandle;Row,Column:INTEGER);
  650. VAR aCell:Point;
  651. BEGIN
  652.     aCell.H:=0;
  653.     aCell.V:=0;
  654.     IF LGetSelect(TRUE,aCell,List) THEN
  655.                                         LSetSelect(FALSE,aCell,List);
  656.     aCell.H:=Column;
  657.     aCell.V:=Row;
  658.     LSetSelect(TRUE,aCell,List);
  659.     LAutoScroll(List);
  660. END; { LSetSelection }
  661.  
  662. FUNCTION GetDlgData:DlgDataHandle;
  663.  
  664.     { We need to share some data between the SFP Dialog Hook, the File Filtering Function and the
  665.         procedure that actually calls the SFP dialog.
  666.         Because we do not have global variables we use a resource as a record.
  667.         We cannot access to this resource by using its resource ID, so we use its name. }
  668.         
  669. BEGIN
  670.     GetDlgData:=DlgDataHandle(GetNamedResource('DATA','4DPX/SFPGetFile/23001'));
  671. END; { GetDlgData }
  672.  
  673. PROCEDURE DrawListItem(MyDlg:DialogPtr;MyItem:INTEGER);
  674. VAR    ItemRect:Rect;
  675.         FileList:ListHandle;
  676.         UpdateRgn:RgnHandle;
  677. BEGIN
  678.     FileList:=GetDlgData^^.FileList;
  679.     IF FileList<>NIL THEN
  680.     BEGIN
  681.         UpdateRgn:=NewRgn;
  682.         IF UpdateRgn<>NIL THEN
  683.         BEGIN
  684.             CopyRgn(MyDlg^.VisRgn,UpdateRgn);
  685.             LUpdate(UpdateRgn,FileList);
  686.             DisposeRgn(UpdateRgn);
  687.         END;
  688.         GetItemRect(MyDlg,MyItem,ItemRect);
  689.         FrameRect(ItemRect);
  690.     END;
  691. END; { DrawListItem }
  692.  
  693. FUNCTION OpenDlgHook(MyItem:INTEGER;MyDlg:DialogPtr):INTEGER;
  694. CONST    StayInSFDlg        =    0;
  695.             RedrawSFList    =    101;
  696. VAR    vRefNum,Len,Count:INTEGER;
  697.         DirID:LongInt;
  698.         aCell:Point;
  699.         DlgData:DlgDataHandle;
  700.         FileList:ListHandle;
  701.         ItemRect,BoundsRect:Rect;
  702.         Array4D:VarRecPtr;
  703.         FileName:Str255;
  704. BEGIN
  705.     IF MyItem=sfHookFirstCall THEN                                                        { Is it the Initialization phase ? }
  706.     BEGIN
  707.         DlgData:=GetDlgData;                                                                        { Get our resource }
  708.         IF DlgData^^.SFDlgID=kOpenMFile THEN                                        { Is it the multiple open dialog? }
  709.         BEGIN
  710.             GetItemRect(MyDlg,kListItem,ItemRect);                                { Get the rectangle of the item }
  711.             InsetRect(ItemRect,1,1);                                                            { Make room for its frame }
  712.             WITH ItemRect DO
  713.             BEGIN
  714.                 Right:=Right-15;                                                                        { Make room for the vertical scroll bar }
  715.                 aCell.H:=Right-Left;                                                                { Cell width = List width }
  716.                 aCell.V:=16;                                                                                { Cell height = 16 pt for Chicago font }
  717.             END;
  718.             SetRect(BoundsRect,0,0,3,0);                                                    { 0 row, 3 columns }
  719.             FileList:=LNew(ItemRect,BoundsRect,aCell,0,
  720.                                          MyDlg,TRUE,FALSE,FALSE,TRUE);                    { Create the list }
  721.             IF FileList<>NIL THEN                                                                    { Was it possible? }
  722.             BEGIN
  723.                 WITH FileList^^ DO
  724.                 BEGIN
  725.                     SelFlags:=lOnlyOne;                                                                { We can select only one cell at a time }
  726.                     ListFlags:=lDoVAutoscroll;                                                { Only automatic vertical scrolling }
  727.                 END;
  728.                 DlgData^^.FileList:=FileList;                                                { Save the handle }
  729.             END;
  730.             MySetUItem(MyDlg,kListItem,@DrawListItem);                        { Set up our user proc. }
  731.             HiliteCtlItem(MyDlg,kRemoveItem,255);                                    { Remove is initially dimmed }
  732.             HiliteCtlItem(MyDlg,kDoneItem,255);                                        { Done is initially dimmed }
  733.         END;
  734.     END
  735.     ELSE
  736.     BEGIN
  737.         IF ((MyItem>0) & (MyItem<100)) | (MyItem>=$1000) THEN    { Avoid the fake items }
  738.         BEGIN
  739.             DlgData:=GetDlgData;                                                                    { Get our resource }
  740.             If DlgData^^.SFDlgID=kOpenMFile THEN                                    { Is it the multiple open dialog? }
  741.             BEGIN
  742.                 FileList:=DlgData^^.FileList;
  743.                 IF FileList<>NIL THEN                                                                { Does the list exist? }
  744.                 BEGIN
  745.                     IF MyItem>=$1000 THEN                                                            { Is it a keyboard event? }
  746.                     BEGIN
  747.                         Len:=LNbOfRows(FileList);                                                { Number of files in our list }
  748.                         Count:=LGetSelection(FileList);                                    { Selected file, if any }
  749.                         IF (MyItem-$1000)=BackSpace THEN                                { Delete key? }
  750.                         BEGIN
  751.                             IF Count>=0 THEN                                                            { Is there a file selected? }
  752.                             BEGIN
  753.                                 MyItem:=kRemoveItem;                                                { If so, execute the code associated
  754.                                                                                                                             with the button Remove }
  755.                                 HiliteDlgButton(MyDlg,kRemoveItem);                    { Just for cosmetic purpose }
  756.                             END;
  757.                         END
  758.                         ELSE
  759.                         BEGIN
  760.                             IF KeyIsDown(OptionKeyCode) THEN                            { Is the Option key pressed? }
  761.                             BEGIN
  762.                                 IF Len>0 THEN                                                                { Is our list empty? }
  763.                                 BEGIN
  764.                                     Len:=Len-1;                                                                { If not, test if we pressed the
  765.                                                                                                                             Up or the Down arrow key }
  766.                                     IF Count>=0 THEN
  767.                                     BEGIN
  768.                                         CASE MyItem-$1000 OF
  769.                                             AsciiUp:
  770.                                             BEGIN
  771.                                                 Count:=Count-1;
  772.                                                 IF Count<0 THEN Count:=Len;
  773.                                                 MyItem:=kListItem;
  774.                                             END;
  775.                                             AsciiDown:
  776.                                             BEGIN
  777.                                                 Count:=Count+1;
  778.                                                 IF Count>Len THEN Count:=0;
  779.                                                 MyItem:=kListItem;
  780.                                             END;
  781.                                         END;
  782.                                         IF MyItem=kListItem THEN                                { It was one of these two keys }
  783.                                         BEGIN
  784.                                             LSetSelection(FileList,Count,0);            { Move the selection }
  785.                                             MyItem:=0;                                                        { No more thing to do }
  786.                                         END;
  787.                                     END; { Empty selection? }
  788.                                 END; { Empty list? }
  789.                             END; { OptionKey? }
  790.                         END; { Backspace ? }
  791.                     END; { IF MyItem>=$1000 THEN }
  792.                     IF MyItem<$1000 THEN
  793.                     BEGIN
  794.                         CASE MyItem OF
  795.                             GetOpen:                                                                            { We clicked on the Add button }
  796.                             BEGIN
  797.                                 FileName:=DlgData^^.UserReplyPtr^.FName;        { Get the file name from the reply }
  798.                                 vRefNum:=-IntegerPtr(SFSaveDisk)^;                    { Get the volume reference number }
  799.                                 DirID:=LongIntPtr(CurDirStore)^;                        { Get the parent directory ID }
  800.                                 Count:=LSearchFile(@FileName,
  801.                                                                      vRefNum,
  802.                                                                      DirID,
  803.                                                                      FileList,Len);                        { Check if the file is already selected }
  804.                                 IF Len>=0 THEN
  805.                                     LSetSelection(FileList,Len,0)                          { If so, just select it }
  806.                                 ELSE
  807.                                 BEGIN
  808.                                     Count:=LAddRow(1,Count,FileList);                    { Insert a new row }
  809.                                     IF Count>=0 THEN        
  810.                                     BEGIN
  811.                                         LPutString(FileList,Count,0,@FileName);    { Save the file name }
  812.                                         LPutInteger(FileList,Count,1,vRefNum);    { Save the volume reference number }
  813.                                         LPutLongInt(FileList,Count,2,DirID);        { Save the parent directory ID }
  814.                                         LSetSelection(FileList,Count,0);                { Select the new line }
  815.                                     END;
  816.                                 END;
  817.                             END; { GetOpen }
  818.                             
  819.                             GetCancel,kDoneItem:                                                    { We leave the dialog }
  820.                             BEGIN
  821.                                 Array4D:=DlgData^^.Array4D;                                    { Get a pointer to the 4D array }
  822.                                 ClearArray(Array4D^);                                                { In any case, we clear the 4D array }
  823.                                 IF MyItem=kDoneItem THEN                                        { We clicked on the Done button }
  824.                                 BEGIN
  825.                                     IF Array4D^.VarKind
  826.                                                         IN [TabAlpha,TabStrFix] THEN        { If the type of the array is valid }
  827.                                     BEGIN
  828.                                         Len:=LNbOfRows(FileList);
  829.                                         IF Len>0 THEN                                                      { If there is at least one file }
  830.                                         BEGIN
  831.                                             IF ResizeArray(Array4D^,
  832.                                                                 ORD4(Len))=NoErr THEN              { Set the new size of the array }
  833.                                             BEGIN
  834.                                                 FOR Count:=0 TO Len-1 DO                        { For each row:
  835.                                                                                                                             - Get the file name,
  836.                                                                                                                             - The volume reference number,
  837.                                                                                                                             - The parent directory ID,
  838.                                                                                                                             - Calculate the path name,
  839.                                                                                                                             - Insert this latter in the array. }
  840.                                                 BEGIN
  841.                                                     LGetString(FileList,Count,0,@FileName);
  842.                                                     GetPathName(LGetInteger(FileList,Count,1),
  843.                                                                             LGetLongInt(FileList,Count,2),@FileName);
  844.                                                     IF NOT(AddStringElement(@FileName,1+ORD4(Count),Array4D)) THEN LEAVE;
  845.                                                 END;
  846.                                             END;
  847.                                         END;
  848.                                     END;
  849.                                 END;
  850.                                 LDispose(FileList);                                                    { We do not need the list anymore }
  851.                                 DlgData^^.FileList:=NIL;
  852.                             END; { GetCancel,kDoneItem }
  853.                             kListItem:                                                                        { We clicked on our list }
  854.                             BEGIN
  855.                                 GetMouse(aCell);                                                        { Where is the mouse? }
  856.                                 IF LClick(aCell,0,FileList) THEN                        { Is it a double-click? }
  857.                                 BEGIN
  858.                                     HiliteDlgButton(MyDlg,kRemoveItem);                { Just for cosmetic purpose }
  859.                                     LDeleteSelection(FileList);                                { If so, remove the file from the list }
  860.                                 END;
  861.                             END; { kListItem }
  862.                             kRemoveItem:                                                                    { We clicked on the Remove button }
  863.                                 LDeleteSelection(FileList);                                    { Remove the file from the list }
  864.                         END; { CASE MyItem OF }
  865.                     END; { Keyboard event? }
  866.                     IF LNbOfRows(FileList)>0 THEN
  867.                         Count:=0 ELSE Count:=255;
  868.                     HiliteCtlItem(MyDlg,kDoneItem,Count);                            { Update the state of the button Done }
  869.                     IF LGetSelection(FileList)>=0 THEN
  870.                         Count:=0 ELSE Count:=255;
  871.                     HiliteCtlItem(MyDlg,kRemoveItem,Count);                        { Update the state of the button Remove }
  872.                 END; { IF FileList<>NIL THEN }
  873.                 
  874.                 CASE MyItem OF
  875.                     GetOpen            : MyItem:=StayInSFDlg;                                { We stay in the dialog }
  876.                     kDoneItem        :    MyItem:=GetCancel;                                    { We leave the dialog }
  877.                 END; { CASE MyItem OF }
  878.                 
  879.             END; { If DlgData^^.DlgID=kOpenMFile THEN }
  880.         END; { IF (MyItem>0) & (MyItem<100) THEN }
  881.     END;
  882.     OpenDlgHook:=MyItem;                                                                            { Do not forget! }
  883. END; { OpenDlgHook }
  884.  
  885. FUNCTION OpenFileFilter(FileBlk:HParmBlkPtr):BOOLEAN;
  886. VAR    FunctionText:Handle;
  887.         Str:Str255;
  888. BEGIN
  889.     OpenFileFilter:=TRUE;
  890.     FunctionText:=NewHandle(0);
  891.     IF FunctionText<>NIL THEN
  892.     BEGIN
  893.         Str:=FileBlk^.ioNamePtr^;
  894.         GetPathName(-IntegerPtr(SFSaveDisk)^,LongIntPtr(CurDirStore)^,@Str);
  895.         SetDocumentVar(@Str);
  896.         
  897.         Str:=GetDlgData^^.FilterProc;
  898.         AddStringToText(@Str,FunctionText);
  899.         OpenFileFilter:=NOT(Call4DLongIntFunction(FunctionText)>0);
  900.         
  901.         { IMPORTANT NOTE
  902.             --------------
  903.             Calling back 4th DIMENSION from the File Filtering Function may introduce some effects:
  904.             - Displaying the list of the files will be slow down. It will take as long as the time
  905.             to execute the 4th DIMENSION function for each file to be displayed. This factor is important
  906.             especially if you run an interpreted database.
  907.             - If you trace the 4th DIMENSION function, remember that the 4D code is executing outside any
  908.             regular execution cycle. Subsequently, 4th DIMENSION will not close the Trace window.
  909.         }
  910.         
  911.     END;
  912. END; { OpenFileFilter }
  913.  
  914.  
  915. PROCEDURE FILES_PACKAGE;
  916.         
  917.     PROCEDURE    CustSFGetFile(FileName:Ptr;DlgID,L,T:INTEGER;FilterProcName,Message:StringPtr);
  918.     VAR    Where:Point;
  919.             CurPort:GrafPtr;
  920.             TypeList: SFTypeList;
  921.             UserReply:SFReply;
  922.             DlgData:DlgDataHandle;
  923.     BEGIN
  924.         DlgData:=GetDlgData;
  925.         IF DlgData<>NIL THEN
  926.         BEGIN
  927.             HNoPurge(Handle(DlgData));
  928.             WITH DlgData^^ DO
  929.             BEGIN
  930.                 SFDlgID:=DlgID;
  931.                 UserReplyPtr:=SFReplyPtr(@UserReply);
  932.                 FileList:=NIL;
  933.                 IF DlgID=kOpenMFile THEN Array4D:=VarRecPtr(FileName) ELSE Array4D:=NIL;
  934.                 IF Length(FilterProcName^)>63 THEN FilterProcName^[0]:=Chr(63);
  935.                 FilterProc:=FilterProcName^;
  936.             END;
  937.             Where.H:=L;
  938.             Where.V:=T;
  939.             GetPort(CurPort);
  940.             ParamText(Message^,'','','');
  941.             SFPGetFile(Where,
  942.                                  '',
  943.                                  @OpenFileFilter,
  944.                                  -1,TypeList,
  945.                                  @OpenDlgHook,
  946.                                  UserReply,
  947.                                  GetResNum('4BNX','DLOG',DlgID),
  948.                                  NIL);
  949.             SetPort(CurPort);
  950.             IF DlgID=kOpenSFile THEN
  951.             BEGIN
  952.                 WITH UserReply DO
  953.                 BEGIN
  954.                     IF Good THEN
  955.                     BEGIN
  956.                         StringPtr(FileName)^:=FName;
  957.                         GetPathName(vRefNum,LongIntPtr(CurDirStore)^,StringPtr(FileName));
  958.                     END
  959.                     ELSE StringPtr(FileName)^:='';
  960.                 END; { WITH UserReply DO }
  961.             END; { IF DlgID=kOpenSFile THEN }
  962.             HPurge(Handle(DlgData));
  963.         END; { IF DlgData<>NIL THEN }
  964.     END; { CustSFGetFile }
  965.  
  966.     PROCEDURE DoGetFileInfo;
  967.     VAR    Count:INTEGER;
  968.             ParamBlk:ParamBlockRec;
  969.             FileName:Str255;
  970.     
  971.         PROCEDURE DoSecs2Date(Secs:LongInt;VAR aDate:Date4D;VAR aTime:LongInt);
  972.         VAR    aMacDate:DateTimeRec;
  973.         BEGIN
  974.             Secs2Date(Secs,aMacDate);
  975.             WITH aMacDate DO
  976.             BEGIN
  977.                 aDate.Year:=Year;
  978.                 aDate.Month:=Month;
  979.                 aDate.Day:=Day;
  980.                 aTime:=ORD4(Hour)*3600+ORD4(Minute)*60+ORD4(Second);
  981.             END;
  982.         END; { DoSecs2Date }
  983.     
  984.     BEGIN
  985.         FileName:=StringPtr(Params^[1])^;
  986.         WITH ParamBlk DO
  987.         BEGIN
  988.             ioCompletion:=NIL;
  989.             ioNamePtr:=@FileName;
  990.             ioVRefNum:=0;
  991.             ioFVersNum:=0;
  992.             ioFDirIndex:=-1;
  993.         END;
  994.         IF PBGetFInfo(@ParamBlk,FALSE)=NoErr THEN
  995.         BEGIN
  996.             WITH ParamBlk DO
  997.             BEGIN
  998.                 FOR Count:=1 TO 4 DO
  999.                 BEGIN
  1000.                     StringPtr(Params^[2])^[Count]:=ioFlFndrInfo.fdType[Count];
  1001.                     StringPtr(Params^[3])^[Count]:=ioFlFndrInfo.fdCreator[Count];
  1002.                 END;
  1003.                 StringPtr(Params^[2])^[0]:=Chr(4);
  1004.                 StringPtr(Params^[3])^[0]:=Chr(4);
  1005.                 LongIntPtr(Params^[4])^:=ioFlLgLen;
  1006.                 LongIntPtr(Params^[5])^:=ioFlPyLen;
  1007.                 LongIntPtr(Params^[6])^:=ioFlRLgLen;
  1008.                 LongIntPtr(Params^[7])^:=ioFlRPyLen;
  1009.                 DoSecs2Date(ioFlCrDat,Date4DPtr(Params^[8])^,LongIntPtr(Params^[10])^);
  1010.                 DoSecs2Date(ioFlMdDat,Date4DPtr(Params^[9])^,LongIntPtr(Params^[11])^);
  1011.             END;
  1012.         END
  1013.         ELSE
  1014.         BEGIN
  1015.             FOR Count:=2 TO 3 DO StringPtr(Params^[Count])^:='';
  1016.             StringPtr(Params^[3])^:='';
  1017.             FOR Count:=4 TO 7 DO LongIntPtr(Params^[Count])^:=0;
  1018.             FOR Count:=10 TO 11 DO LongIntPtr(Params^[Count])^:=0;
  1019.             FOR Count:=8 TO 9 DO
  1020.             BEGIN
  1021.                 WITH Date4DPtr(Params^[Count])^ DO
  1022.                 BEGIN
  1023.                     Year:=0;
  1024.                     Month:=0;
  1025.                     Day:=0;
  1026.                 END;
  1027.             END;
  1028.         END;
  1029.     END; { DoGetFileInfo }
  1030.  
  1031. BEGIN { FILES_PACKAGE }
  1032.     IF ProcNum>0 THEN
  1033.     BEGIN
  1034.         CASE ORD(ProcNum) OF
  1035.         
  1036.                 { OpenMFile(FileNames;Left;Top;FilterProc;Message)
  1037.                     OpenMFile(Array;Number;Number;String;String)
  1038.                     OpenMFile(&S;&L;&L;&S;&S)
  1039.                     
  1040.                     OpenSFile(FileName;Left;Top;FilterProc;Message)
  1041.                     OpenSFile(String;Number;Number;String;String)
  1042.                     OpenSFile(&S;&L;&L;&S;&S) }
  1043.                     
  1044.             kOpenMFile,kOpenSFile:
  1045.                 CustSFGetFile(Ptr(Params^[1]),
  1046.                                             ORD(ProcNum),
  1047.                                             IntegerPtr(Params^[2])^,
  1048.                                             IntegerPtr(Params^[3])^,
  1049.                                             StringPtr(Params^[4]),
  1050.                                             StringPtr(Params^[5]));
  1051.             
  1052.                 { SetFPos(Document RefNum;MarkerPosition) -> OS Error
  1053.                     SetFPos(Number;Number) -> Number
  1054.                     SetFPos(&L;&L):L }
  1055.                     
  1056.             kSETFPOS:
  1057.                 FuncPtr:=Ptr(ORD4(SetFPos(ORD(LongIntPtr(Params^[1])^),
  1058.                                                                                 fsFromStart,LongIntPtr(Params^[2])^)));
  1059.             
  1060.                 { GetEOF(Document RefNum;Size of the document in bytes) -> OS Error
  1061.                     GetEOF(Number;NumericVar) -> Number
  1062.                     GetEOF(&L;&L):L }
  1063.                     
  1064.             kGETEOF:    
  1065.                 FuncPtr:=Ptr(ORD4(GetEOF(ORD(LongIntPtr(Params^[1])^),LongIntPtr(Params^[2])^)));
  1066.                 
  1067.                 
  1068.                 {    GetFileInfo(Document;Type;Creator;DataLgLen;DataPyLen;ResLgLen;ResPyLen;
  1069.                                                                                                                             CrDate;MdDate;CrTime;MdTime)
  1070.                     GetFileInfo(String;String;String;LongInt;LongInt;LongInt;LongInt;
  1071.                                                                                                                             Date;Date;LongInt;LongInt)
  1072.                     GetFileInfo(&S;&S;&S;&L;&L;&L;&l;&D;&D;&L;&L) }
  1073.                     
  1074.             kGetFileInfo:
  1075.                 DoGetFileInfo;
  1076.                 
  1077.                 
  1078.         END; { CASE ORD(ProcNum) OF }
  1079.     END
  1080.     ELSE IF ProcNum=Init4DPackage THEN ShowDevToolDlg;
  1081. END; { FILES_PACKAGE }
  1082.  
  1083. END. { EXT4D_FILES_PACKAGE }